# 函数定义中可能包含多个形参，因此函数调用中也可能包含多个实参。
# 向函数传递实参的方式很多，可使用位置实参，这要求实参的顺序与形参的顺序相同；
# 也可使用关键字实参，其中每个实参都由变量名和值组成；还可使用列表和字典。

print("------------8.2.1 位置实参-------------")
# 在调用函数时，Python 必须将函数调用中的每个实参关联到函数定义中的一个形参。
# 最简单的方式是基于实参的顺序进行关联。以这种方式关联的实参称为位置实参。

def describe_pet(animal_type, pet_name):
    """显示宠物的信息"""
    print("\nI have a " + animal_type + ".")
    print("My " + animal_type + "'s name is " + pet_name.title() + ".")

describe_pet('hamster', 'harry')
# 调用函数多次
describe_pet('dog', 'willie')

# 位置实参的顺序很重要，下面的实参顺序不同，导致结果不同
describe_pet('harry', 'hamster')

print("------------8.2.2 关键字实参-------------")
# 关键字实参是传递给函数的名值对。
# 这样会直接在实参中将名称和值关联起来，因此向函数传递实参时就不会混淆了
# 关键字实参的顺序无关紧要，因为 Python 知道各个值该存储到哪个形参中
describe_pet(animal_type='hamster', pet_name='harry')
describe_pet(pet_name='harry', animal_type='hamster')
# 这次调用这个函数时，向Python 明确地指出了各个实参对应的形参

print("------------8.2.3 默认值-------------")
# 编写函数时，可给每个形参指定默认值
# 在调用函数中给形参提供了实参时，Python 将使用指定的实参值；
# 否则，将使用形参的默认值。
# 因此，给形参指定默认值后，可在函数调用中省略相应的实参

# 给形参指定默认值后，等号两边不要有空格
# 非默认形参放在默认形参前面，否则报错
def describe_pet(pet_name, animal_type='dog'):
    """显示宠物的信息"""
    print("\nI have a " + animal_type + ".")
    print("My " + animal_type + "'s name is " + pet_name.title() + ".")

describe_pet(pet_name='willie')
# 注意：当使用默认值时，必须在形参列表中先列出没有默认值的形参，再列出有默认值的形参。
# 这让 Python 依然能够正确地解读位置实参。

print("------------8.2.4 等效的函数调用-------------")
# 鉴于可混合使用位置实参、关键字实参和默认值，通常有多种等效的函数调用方式。
# 鉴于这种灵活性，应尽量避免使用默认值
# 除非你需要指定默认值，否则最好只使用位置实参和关键字实参调用函数

def describe_pet(pet_name, animal_type='dog'):
    """显示宠物的信息"""
    print("\nI have a " + animal_type + ".")
    print("My " + animal_type + "'s name is " + pet_name.title() + ".")

# 基于这种定义，在任何情况下都必须给 pet_name 提供实参。
# 在指定该实参时，既可以使用位置实参，也可以使用关键字实参。
# 使用位置实参时，由于该实参是第一个，因此 Python 将这个值存储到形参 pet_name 中。
describe_pet('willie')
# 使用关键字实参时，由于指定了给哪个形参赋值，因此不会混淆
describe_pet(pet_name='willie')

# 使用位置实参
describe_pet('harry', 'hamster')
# 使用关键字实参
describe_pet(pet_name='harry', animal_type='hamster')
# 使用关键字实参，就可以任意打乱顺序
describe_pet(animal_type='hamster', pet_name='harry')

print("------------8.2.5 避免实参错误-------------")
# 避免实参错误的方式有很多种
# 下面的例子中，函数调用中缺少一个位置实参
# describe_pet()

# 下面的例子中，函数调用中缺少一个关键字实参
describe_pet('harry')

